package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AssertUtil;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.util.Asserts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
    @Autowired
    private AlbumInfoMapper albumInfoMapper;
    @Autowired
    private TrackStatMapper trackStatMapper;
    @Autowired
    private VodService vodService;
    @Autowired
    private AlbumStatMapper albumStatMapper;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveTrackInfo(TrackInfo trackInfo) {
        //1、设置userId
        trackInfo.setUserId(AuthContextHolder.getUserId());
        //2、设置OrderNum  当前声音在专辑中的序号  基于上一个声音序号+1
        //查询声音表中的 当前专辑下的 最后上传的声音序号
        int orderNum = 1;
        TrackInfo lastTrackInfo = trackInfoMapper.selectOne(Wrappers.lambdaQuery(TrackInfo.class)
                .select(TrackInfo::getOrderNum)
                .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                .orderByDesc(TrackInfo::getOrderNum)
                .last("limit 1"));
        if(lastTrackInfo!=null){
            orderNum = lastTrackInfo.getOrderNum()+1;
        }
        trackInfo.setOrderNum(orderNum);
        //3、设置音频属性相关的值
        //vod支持 根据音频id查询媒体资源信息

        TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackMediaInfoVo(trackInfo.getMediaFileId());
        trackInfo.setMediaType(trackMediaInfoVo.getType());
        trackInfo.setMediaSize(trackMediaInfoVo.getSize());
        trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));
        //4、审核、来源 状态
        trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
        //5、保存声音
        trackInfoMapper.insert(trackInfo);

        //6、更新专辑 声音数量
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()+1);
        albumInfoMapper.update(null , Wrappers.lambdaUpdate(AlbumInfo.class)
                .set(AlbumInfo::getIncludeTrackCount , albumInfo.getIncludeTrackCount())
                .eq(AlbumInfo::getId , albumInfo.getId()));

        //7、初始化声音统计数据  保存到track_stat表中
        this.saveTrackStat(trackInfo.getId() , SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId() , SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId() , SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId() , SystemConstant.TRACK_STAT_COMMENT);
    }
    private void saveTrackStat(Long trackId , String type){
        TrackStat trackStat = new TrackStat();
        trackStat.setStatNum(0);
        trackStat.setTrackId(trackId);
        trackStat.setStatType(type);
        trackStatMapper.insert(trackStat);
    }

    @Override
    public Page<TrackListVo> findUserTrackPage(Long pageNum, Long pageSize, TrackInfoQuery trackInfoQuery) {

        trackInfoQuery = trackInfoQuery==null ? new TrackInfoQuery():trackInfoQuery;
        trackInfoQuery.setUserId(AuthContextHolder.getUserId());

        return trackInfoMapper.selectUserTrackPage(new Page<TrackListVo>(pageNum,pageSize) ,trackInfoQuery);
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeTrackInfo(Long id) {
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        //1、删除声音
        trackInfoMapper.deleteById(id);
        //2、删除声音统计数据
        trackStatMapper.delete(Wrappers.lambdaQuery(TrackStat.class)
                .eq(TrackStat::getTrackId , id));
        //3、更新专辑声音数量
//        albumInfoMapper.selectById()
        albumInfoMapper.decrementTrackCount(trackInfo.getAlbumId(),1);
        //4、删除vod中的声音
        vodService.deleteVodMedia(trackInfo.getMediaFileId());


    }

    @Override
    public TrackInfo getTrackInfo(Long id) {
        return trackInfoMapper.selectById(id);
    }

    @Override
    public void updateTrackInfo(Long id, TrackInfo trackInfo) {
        //1、查询更新前的声音的 id
        TrackInfo dbTrackInfo = trackInfoMapper.selectById(id);
        String dbMediaFileId = dbTrackInfo.getMediaFileId();
        //2、判断声音是否修改了：
        // 如果修改了 需要获取修改上传的声音的媒体信息 设置给trackInfo
        //     还需要删除旧的声音
        if(!dbMediaFileId.equals(trackInfo.getMediaFileId())){
            //声音文件修改了
            TrackMediaInfoVo mediaInfoVo = vodService.getTrackMediaInfoVo(trackInfo.getMediaFileId());
            //删除旧的音频文件的id
           vodService.deleteVodMedia(dbMediaFileId);
           //将新的声音的属性设置给trackInfo
            trackInfo.setMediaUrl(mediaInfoVo.getMediaUrl());
            trackInfo.setMediaDuration(new BigDecimal(mediaInfoVo.getDuration()));
            trackInfo.setMediaSize(mediaInfoVo.getSize());
            trackInfo.setMediaType(mediaInfoVo.getType());
        }
        //3、更新trackInfo数据
        trackInfoMapper.updateById(trackInfo);

    }
    /*
        单元测试：
        压力测试： ab jmeter
        白盒测试：
        AB测试：
                通过不同的数据测试(正反数据)
     */
    //专辑详情页：查询声音分页列表
    @Override
    public Page<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Long pageNum, Long pageSize) {
        //1、查询声音的分页列表数据: 使用专辑id分页查询声音列表、按照orderNum升序排列，统计播放和评论数
        //包含： track_info表、 track_stat表、 声音的付费标识(service-user服务：user_paid_track表 )
        Page<AlbumTrackListVo> page = trackInfoMapper
                .selectAlbumTrackPage( new Page<AlbumTrackListVo>(pageNum,pageSize) , albumId);
        //2、声音付费标识设置
        Long userId = AuthContextHolder.getUserId();
        //2.1 用户未登录： 免费的 或者 收费可以试听的声音 设置为无需付费 其它设置为需要付费
        //> 1、查询声音所属的专辑信息： 包含了专辑收费类型
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        if(userId==null){
            if(!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())){
                //需要收费
                //设置 试听以外的声音为收费标识
                page.getRecords().forEach(albumTrackListVo -> {
//                    albumInfo.getTracksForFree()免费试听的声音集数
                    //声音有序号，从1开始   如果序号大于免费试听的声音集数 设置为收费
                    if(albumTrackListVo.getOrderNum().intValue()>albumInfo.getTracksForFree().intValue()){
                        albumTrackListVo.setIsShowPaidMark(true);
                    }
                });
            }
        }
        //2.2 用户已登录：
        //      1- 声音vip免费：  判断用户如果是vip设置无需付费
        //      2- 声音需要购买：  判断用户是否购买 已购买设置为无需付费
        //           否则可以试听的声音无需付费  其它设置为需要付费
        else{
            //查询用户信息： 是不是vip 、vip是否过期(以后通过定时任务更新，为了防止vip已过期未来得及更新 需要主动判断)
            Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfo(userId);
            AssertUtil.resultAssert(userInfoVoResult, ResultCodeEnum.DATA_ERROR);
            UserInfoVo userInfoVo = userInfoVoResult.getData();
            //> 1、专辑vip免费
            boolean isNeedPaid = true;
            if(SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())){//专辑vip免费
                // 如果用户不是vip   、用户是vip但是已过期  可能要收费
                if(userInfoVo.getIsVip().intValue()!=1 ||
                        (userInfoVo.getIsVip().intValue()==1

                                && (userInfoVo.getVipExpireTime()==null
                                || userInfoVo.getVipExpireTime().before(new Date())))

                ){
                    isNeedPaid = true;
                }else{
                    //用户是vip 并且专辑vip免费
                    isNeedPaid = false;
                }
            }
            //> 2、专辑需要购买
            else if(SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())){
                isNeedPaid = true;
            }
            //> 3、专辑免费
            else {
                isNeedPaid = false;
            }
            // 专辑需要用户付费
            if(isNeedPaid){
                //查询用户购买过的该专辑下的声音id列表： 可以使用Set来存储(去重、判断一个值是否存在 时间复杂度O1)
                Result<Set<Long>> setResult = userInfoFeignClient.getPaidTrackIds(userId, albumId);
                AssertUtil.resultAssert(setResult,ResultCodeEnum.DATA_ERROR);
                Set<Long> paidTrackIds = setResult.getData();
                //遍历每个声音 判断用户是否购买过 如果为购买设置 付费标识
               page.getRecords().forEach(albumTrackListVo -> {
                   //跳过免费试听的声音
                   if(albumTrackListVo.getOrderNum().intValue()> albumInfo.getTracksForFree().intValue()){
                       //判断 没有购买的声音设置付费标识
                       if(CollectionUtils.isEmpty( paidTrackIds) ||
                               !paidTrackIds.contains(albumTrackListVo.getTrackId())){
                           albumTrackListVo.setIsShowPaidMark(true);
                       }
                   }
               });

            }

        }

        return page;
    }

    @Override
    public void updateTrackStat(TrackStatMqVo vo) {
        Long trackId = vo.getTrackId();
        Integer count = vo.getCount();
        String statType = vo.getStatType();

        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

        trackStatMapper.updateTrackStat(trackId , count , statType);
        if(SystemConstant.TRACK_STAT_PLAY.equals(statType)){
            albumStatMapper.updateAlbumStat(trackInfo.getAlbumId() , count , SystemConstant.ALBUM_STAT_PLAY);
        }

    }

    @Override
    public List<TrackOrderVo> findUserTrackPaidList(Long id) {
        //1、根据声音id 查询专辑(如果专辑是vip免费！！)
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        Assert.notNull(trackInfo , "声音不存在！");
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
        Assert.notNull(albumInfo , "专辑不存在！");
        //2、根据专辑id查询当前声音orderNum及以后的声音列表
        if(albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)){
            Assert.notNull(albumInfo , "专辑免费,不需要购买！");
        }
        if(trackInfo.getOrderNum() <= albumInfo.getTracksForFree()){
            Assert.notNull(albumInfo , "声音免费,不需要购买！");
        }
        //查询用户信息：如果专辑vip免费 用户是vip 不处理
        List<Long> needPaidTrackIds = trackInfoMapper.selectList(Wrappers.lambdaQuery(TrackInfo.class)
                        .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                        .ge(TrackInfo::getOrderNum, trackInfo.getOrderNum())
                        .select(TrackInfo::getId))
                .stream().map(TrackInfo::getId).collect(Collectors.toList());

        //3、查询用户该专辑已购买的声音id列表: service-user： user_paid_track
        Result<Set<Long>> paidTrackIdsResult = userInfoFeignClient.getPaidTrackIds(AuthContextHolder.getUserId(),
                trackInfo.getAlbumId());
//        AssertUtil.resultAssert(paidTrackIdsResult,ResultCodeEnum.DATA_ERROR);
//        Assert.isTrue(paidTrackIdsResult!, "用户已购买声音列表查询失败" );
        if (paidTrackIdsResult == null
                || !paidTrackIdsResult.getCode().equals(ResultCodeEnum.SUCCESS.getCode())) {
            log.error("远程调用失败");
            throw new GuiguException(ResultCodeEnum.DATA_ERROR);
        }

        //4、挑出第二步查询到的 用户未购买的声音id列表
        Set<Long> paidTrackIds = paidTrackIdsResult.getData();
        if(!CollectionUtils.isEmpty(paidTrackIds)){
            needPaidTrackIds = needPaidTrackIds.stream().filter(needPaidTrackId->
                    !paidTrackIds.contains(needPaidTrackId))
                    .collect(Collectors.toList());
        }
        //5、根据剩余的声音列表 生成 可以购买集数的方案
        if(needPaidTrackIds.size()==0){ //没有需要购买的声音
            throw new GuiguException(ResultCodeEnum.DATA_ERROR);
        }
        List<TrackOrderVo> trackOrderVos = new ArrayList<>();
        //5.1 购买本集的方案: 调用方法后返回对象本身
        trackOrderVos.add(new TrackOrderVo().setName("本集")
                .setPrice(albumInfo.getPrice())//专辑的价格是一个声音的价格
                .setTrackCount(0)
        );
        //5.2 后五级
        if(needPaidTrackIds.size()>=5){
            trackOrderVos.add(new TrackOrderVo().setName("后5集")
                    .setPrice(albumInfo.getPrice().multiply(new BigDecimal("5")))//专辑的价格是一个声音的价格
                    .setTrackCount(5)
            );
        }
        //5.3 后10级
        if(needPaidTrackIds.size()>=10){
            trackOrderVos.add(new TrackOrderVo().setName("后10集")
                    .setPrice(albumInfo.getPrice().multiply(new BigDecimal("10")))//专辑的价格是一个声音的价格
                    .setTrackCount(10)
            );
        }
        //5.4 后所有级
        if(needPaidTrackIds.size()>0){
            trackOrderVos.add(new TrackOrderVo().setName("后"+needPaidTrackIds.size()+"集")
                    .setPrice(albumInfo.getPrice().multiply(new BigDecimal(needPaidTrackIds.size()+"")))//专辑的价格是一个声音的价格
                    .setTrackCount(needPaidTrackIds.size())
            );
        }
        //5.5 vip全集免费  前端自动生成
//        if(albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_VIPFREE)){
//            //vip免费
//            trackOrderVos.add(new TrackOrderVo().setName("vip全集")
//                    .setPrice(albumInfo.getPrice().multiply(new BigDecimal(0+"")))//专辑的价格是一个声音的价格
//                    .setTrackCount(needPaidTrackIds.size())
//            );
//        }
        return trackOrderVos;
    }
}
